package blue.http.internal.core.message;

import blue.base.core.util.AssertUtil;
import blue.http.core.exception.HttpServerException;
import blue.http.core.message.Download;
import blue.http.core.message.DownloadBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;

/**
 * @author zhengjin
 * @since 1.0 2018年03月26日
 */
public class DefaultDownloadBuilder implements DownloadBuilder {
	private static Logger logger = LoggerFactory.getLogger(DefaultDownloadBuilder.class);

	private Download.Type type;
	private byte[] memory;
	private Path path;
	private String filename;
	private boolean download = false;
	private boolean handled = false;

	public DefaultDownloadBuilder() {
	}

	@Override
	public Download build() {
		DefaultDownload dd = new DefaultDownload();
		dd.setDownload(download);
		dd.setPath(path);
		dd.setFilename(filename);
		dd.setMemory(memory);
		dd.setType(type);
		return dd;
	}

	@Override
	public DefaultDownloadBuilder handle(Download.Type type, Consumer<OutputStream> f) {
		if (handled) {
			throw new HttpServerException("handle() 只能调用一次");
		}

		handled = true;
		this.type = (type == null ? Download.Type.MEMORY : type);

		if (type == Download.Type.MEMORY) {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			f.accept(baos);
			memory = baos.toByteArray();
		} else if (type == Download.Type.FILE) {
			try {
				path = Files.createTempFile(null, null);
				if (logger.isDebugEnabled()) {
					logger.debug("Create temp file: {}", path);
				}
			} catch (IOException e) {
				throw new UncheckedIOException(e);
			}
			try (var fos = Files.newOutputStream(path)) {
				f.accept(fos);
			} catch (IOException e) {
				logger.error("Write temp file error, ", e);
			}
		}
		return this;
	}

	@Override
	public DefaultDownloadBuilder setPath(Path path) {
		AssertUtil.notNull(path, "Path");
		if (this.path != null) {
			throw new HttpServerException("setPath() 方法只能调用一次");
		}

		this.path = path;
		return this;
	}

	@Override
	public DefaultDownloadBuilder setFilename(String filename) {
		this.filename = filename;
		return this;
	}

	@Override
	public DefaultDownloadBuilder setDownload(boolean download) {
		this.download = download;
		return this;
	}
}
